home *** CD-ROM | disk | FTP | other *** search
-
-
-
- |====================================|
- | |
- | TELEMACHOS proudly presents : |
- | |
- | Part 5 of the PXD trainers - |
- | |
- | SVGA using VESA 1.2 |
- | |
- | |
- |====================================|
-
- ___---__--> The Peroxide Programming Tips <--__---___
-
- <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
-
-
- Intoduction
- -----------
-
- Hi folks... It's been a while, I know, but I have been busy living my REAL
- life :) (YEAH, I know : REAL LIFE SUXX!)
-
- There have been quite a few people mailing me about my last two tutorials and
- one of them made me discover a little error in my gouraud routines.
- Actually it's not an error - I just presume that there is a maximum of 64
- colors in the shading table. If using more a few variables / regs will overflow
- resulting in graphical errors. The problems can be fixed by reducing the
- shl 8 statement to shl 7 when calculating the fixed point step values.
- Then later on when the vars has been calculated as 9.7 fixed point values you
- just have to multiply them by two to get them back to 8.8 fixed point.
- Now things should work correct.
- Also, in the gouraud polygonside scanner change the type of the variable
- "color" from integer to word.
-
- This tutorial will be on SVGA graphic using the VESA 1.2 BIOS implemention.
- In the past I have seen quite a few shareware SVGA programming libs - but so
- far all of them has sucked pretty much. Either they presume a granularity of
- 64K - or they are written in pure asm without any decent comments - making
- them virtually impossible to learn from.
- Or they use BIOS calls to switch banks which suck just as much as code without
- comments.
- So what we'll do is to build a small pascal/asm SVGA lib that supports *ALL*
- SVGA cards on the market (at least we can try :) ).
- Also I'll try to explain everything about SVGA in a way so that the reader
- actually understands VESA-coding after reading this text.
- If you are bored with theory stop reading right now and skip to the headline
- called "THE CODE". But I strongly recommend you to read the entire text -
- otherwise you'll be coding VESA graphics in half an hour but not understand
- what you're doing :)
-
- BTW. Some lamer seems to find it extremely funny to reset the hit-counter on
- my homepage. If you're reading this : Please don't do it again - it makes me
- very unhappy and I lie fever-striken on my bed for several days each time
- it happen.
- If you really enjoy resetting counters THAT much drop me a mail and I'll code
- you an internet-hit-counter-resetter-simulater FOR FREE!!!!!!!
- If any of you NON-lamers who reads this - you know, the kind of people who
- spend their time actually CODING instead of resetting counters, spreading
- virusses and beating their little brothers - I would like to know if any of
- you know how to make a hit-counter that cannot be reset by the weak-minded
- people of the net.
-
-
- If you want to get in contact with me, there are several ways of doing it :
-
- 1) E-mail me : tm@image.dk
-
- 2) Snail mail me : Kasper Fauerby
- Saloparken 226
- 8300 Odder
- Denmark
-
- 3) Call me (Voice ! ) : +45 86 54 07 60
-
-
- Get this serie from the major demo-related FTP-sites - currently :
-
- GARBO ARCHIVES (forgot the address) : /pc/programming/
-
- ftp.teeri.oulu.fi : /msdos/programming/docs/
-
- ftp.cdrom.com : something with demos/incomming/code.....
-
- Or grap it from my homepage :
-
- Telemachos' Codin' Corner http://www.image.dk/~tm
-
-
-
- WHAT IS VESA AND WHY DO WE NEED IT ?
- ------------------------------------
-
- Well... as you all know the standard mode $13 is a linear mode taking up
- 64000 bytes of memory. This fits into a single segment and therefore it is
- extremely easy to code. When mode $13 was introduced all agreed on using
- segment $a000 as base for the mode. Therefore our mode $13 code will work on
- EVERY SINGLE VGA-card available.
- When SVGA was introduced for the first time it was IBM who developed a very
- expensive GFX-card capable of doing extremely high resolutions - for that time,
- that is.
- But IBM never released the register information for programming the card.
- In time other companies developed SVGA cards - each with their own way of
- laying out the gfx-cards registers. The result was that it became almost
- impossible to code applications for SVGA - if the application was to support
- the different gfx cards the programmers had to do routines for EVERY SINGLE
- gfx card on the market. The result was that most programmers chosed not to
- support SVGA at all. The high resolution was'nt worth the time spend on doing
- the code.
- VESA saw the problem and came up with a BIOS extension that supplied some
- standard routines for coding the different SVGA cards available at the time
- being.
- For a long time it has been VESA 1.2 that has been the standard in SVGA coding.
- But now UniVBE 5.3 has been released making VESA 2.0 available on almost every
- graphic card out there.
- But for us pascal coders VESA 2.0 is pretty uninterresting. First of all :
- The main improvement in VESA 2.0 if something called Linear Frame Buffer (LFB)
- This means that you map your entire VGA-memory into one single linear buffer.
- Then you can adress each pixel on the SVGA screen lineary - just as in good
- old mode $13. But this is obviously only available to those coding in protected
- mode - and I take it that most of my readers are'nt.
- Another thing is that most gfx cards out there only has VESA 1.2 installed -
- so in order to use VESA 2.0 you'll have to assume that the user owns UniVBE 5.3
- So for now we'll stick to good old VESA 1.2
-
-
- THE WORKING OF A SVGA CARD - THE THEORY FOR OUR CODE
- -----------------------------------------------------
-
- As mentioned before each pixel takes up 1 byte of memory. In mode $13 this is
- OK as the screen is only 320 X 200 = 64000 bytes. This way the video memory
- needed for a single screen of graphic fits into one single segment.
- But a SVGA mode takes up much more space. Lets take the standard 640X480 SVGA
- mode. This mode takes up 640 X 480 = 307200 bytes = 4,6875 segments of RAM.
- Hmm... how do we adress all this memory. The modenr for this mode is $101
- Try and set this mode using the following VESA code : (I'll explain the code
- later on)
-
- asm
- mov ah,4Fh
- mov al,02h
- mov bx,$101
- int 10h
- end;
-
- Now try and address the video mem via the good old $a000 segment.... Yes, just
- fill the entire segent with some color. Woila! You have just plotted your first
- pixels in 640 X 480 X 256. But as you might have discovered you are limited to
- accessing only the uppermost part of the screen. The narrow band of graphic you
- see takes up exactly 1 segment of memory.
- What you have just discovered is the greatest pain in SVGA programming :
- the need of windowing. Imagine the entire SVGA-memory laid out lineary. You can
- form it to many different sizes. One size is 640 pixels wide, another 800 and
- yet another 1024. But all the time you only have access to 1 segment of the
- memory. Think of this segment as a window you can look through into the entire
- video memory. Fortunately you can move this window to many different positions
- in the video memory. If you move it around enough you'll discover that you can
- see every byte in video memory through it - just only one segment at a time.
-
- We call all those different window positions for banks. Well, VESA does provide
- us with standard procedures to set the graphic modes, test them and move the
- bank window but still SVGA is a little complicated. First of all there is
- the GRANULARITY of the video card. The granularity decides how the window can
- be moved around in the video memory. A granularity of 64K means that the window
- can be moved only in 64K chunks - ie. an entire window at a time. Some cards
- have finer granularity - Cirrus Logic fx. has a granularity of 4K which allows
- the windows to overlap. Each window position is called a bank even though some
- of the memory can be accesed through multiple window positions.
- The window size is an entirely different matter from the granularity. On most
- cards the window size is 64K (actually on every card I have seen so far) but
- some cards implement 128K. This is however not important to us as the greatest
- granularity is 64K - so as long the window is not below 64K in size we can
- acces all memory by moving the window.
-
- It is pretty safe to assume that the video memory is accesed from the $a000
- segment but to be sure one should always test this by making a BIOS call before
- trying to write to memory. Some cards have multiple windows - We call them
- window A and Window B. This is because some cards have ReadOnly access in one
- window and WriteOnly in another. So this is another thing to check : Can we
- do both our reads and writes in the same window ?
-
-
-
- THE VESA FUNCTIONS EXPLAINED
- -----------------------------
-
- All VESA functions is reached from a sub-function of the BIOS interrupt $10.
- This subfunction is 4Fh so in all interrupt calls we must load the ah register
- with 4Fh and the al register with the VESA function number we want.
-
- I'll just run over the different VESA BIOS functions and then do the code in
- the CODE section.
-
- Function 00h - Return SVGA info
- ---------------------------------
-
- Input : AH : 4Fh
- AL : 00h
- ES:DI : Pointer to 256bytes buffer.
-
- Returns : AX : Status
-
-
- The status register is set up as follows :
-
- AL == 4Fh: Function is supported
- Al != 4Fh: Function is not supported
- AH == 00h: Function call successful
- AH == 01h: Function call failed
-
- Now, as we see we load ah with our VESA subfunction number and AL with the
- VESA function number. ES:DI must point to a 256bytes buffer. This can be any
- buffer of this size. Fx. buffer : Array[0..255] of byte;
- But using a buffer like this leaves us with an enormous amount of converting
- from byte to word and so on... So I'll give you a structure to use instead :
-
-
- TYPE
-
- ListOfAvailModesT = Array[0..255] of word; {terminated by -1 ($FFFF) }
- ListOfAvailModesP = ^ListOfAvailModesT;
-
- VESAInfoT = record
- VESASignature : array[0..3] of byte;
- VESAVersion : word;
- OEMStringPtr : Pchar;
- Capabilities : array[0..3] of byte;
- VideoModePtr : ListOfAvailModesP;
- TotalMemory : word;
- Reserved : Array[0..235] of byte;
- end;
-
- The VESASignature is 4 bytes and when converted to a string they must form the
- word 'VESA'. Otherwise it is not a valid VESA-structure.
-
- The VESAVersion is a word with the high-byte being the major version number and
- the low byte being the minor version number.
-
- OEMStringPtr is a pointer to a 0-terminated String which contains the ident
- string of the SVGA card. But we are in luck - in pascal the type Pchar means
- a pointer to such a string, so we don't have to think any more about this one.
-
- Capabilities is mostly unused. If bit 0 in the first byte is set it means that
- the DAC can be reprogrammed to another DAC width (standard is 6-bit)
-
- VideoModePtr : Now this is a little tricky. This is a pointer to a list of
- words - each word containing a valid graphic mode on the card. The list is
- terminated by -1 ($FFFF).
-
- TotalMemory contains the number of 64K blocks of RAM installed on the card.
-
- The reserved field is reserved for future VESA expansions.
-
-
- This function is the first function your application should run for checking
- if VESA is available at all.
-
-
-
- Function 01h - Return VESA MODE information
- -------------------------------------------
-
- Input : AH = 4Fh
- AL = 01h
- CX = Mode number (must be from the mode list from func 00h)
- ES:DI = pointer to 256 bytes buffer
-
- Returm AX = Status
-
-
- Again I'll give you a structure to use for the 256 bytes buffer. I'll leave out
- some fields for true-color stuff that we will not discuss in this text.
-
- TYPE
-
- ModeAttributesT = (Available,
- Reserved,
- BIOSFunctionsSupport,
- color,
- graphic,
- bit5,
- bit6,
- bit7,
- bit8);
-
-
- WindowAttributesT = (Supported,R,W); {rest of the bits are unused...}
-
-
- VESAModeInfoT = record
- ModeAttributes : set of ModeAttributesT;
- WinAAttributes : set of WindowAttributesT;
- WinBAttributes : set of WindowAttributesT;
- WinGranularity : word;
- WinSize : word;
- WinASegment : word;
- WinBSegment : word;
- BankSwitch : procedure;
- BytesPerScanLine : word;
-
- {Xtended Information}
- XResolution : word;
- YResolution : word;
- XCharSize : byte;
- YCharSize : byte;
- NumberOfPlanes : byte;
- BitsPerPixel : byte;
- NumberOfBanks : byte;
- MemoryModel : byte;
- BankSize : byte;
- NumberOfImagePages : byte;
-
- Reserved : Array[0..225] of byte;
- {reserved is for something we won't think about now...
- true color and stuff... }
- end;
-
-
- WOW.... This sure is a tough one to get through. Well.. to start from the top.
-
- ModeAttributes : This is a word with every bit meaning something different.
- That's why I made the ModeAttributesT. It contains different information about
- the mode from CX. If bit 0 is set the mode is available - if not : Your guess.
- The rest of this field should be obvious from the names in ModeAttributes :
- is it a color mode ? Is it a graphic or text mode? The BIOSSupport field
- decided if you can use BIOS scroll, TTY output and BIOS pixel output in the
- selected mode.
-
- WinAAttributes and WinBAttributes : These are pretty important as they tell you
- if you can read or write to the two windows (A and B). Some cards has only one
- window availble so a window CAN be Read AND Writeable.
-
-
- WinGranularity : This field contains the granularity in KB.
-
- WinSize : The Size of the window in KB.
-
- WinASegent and WinBSegment : This decides where in memory the window base is
- placed. Usually WinASegment will be $A000 - but check it out to be sure.
- If a window reports $0000 as address DON'T use that address :)
-
- BankSwitch : This is a pointer to the hardware bankswitch function. A far call
- can be made to this address for quick bankshifting. Lucky us - pascal allows us
- to use the type "procedure" here so we don't have to worry about the pointer
- stuff... just call this field from an assembler routine. More on this facility
- under function 05h later on.
-
- BytesPerScanLine : The logical number of bytes pr y-line in memory. This is
- usually the same as the maximum x-value in the graphic mode.
-
- The Xtended fields should be pretty self-explaining. One word of warning though.
- I have experienced some problems with the NumberOfBanks and BankSize fields on
- my Cirrus Logic card. Don't trust these fields blindly.
-
-
- function 02 - Set VESA mode
- ----------------------------
-
- Input : AH = 4Fh
- AL = 02h
- BX = Video Mode
- bit 15 : 1 = Don't clear video RAM
- 0 = Clear video RAM
-
-
- Returns : AX = Status
-
-
-
- OK.. Use this one to set the VESA modes. The modes is as follows :
-
-
- GRAPHICS TEXT
-
- 15-bit 7-bit Resolution Colors 15-bit 7-bit Columns Rows
- mode mode mode mode
- number number number number
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 100h - 640x400 256 108h - 80 60
- 101h - 640x480 256
- 109h - 132 25
- 102h 6Ah 800x600 16 10Ah - 132 43
- 103h - 800x600 256 10Bh - 132 50
- 10Ch - 132 60
- 104h - 1024x768 16
- 105h - 1024x768 256
-
- 106h - 1280x1024 16
- 107h - 1280x1024 256
-
- 10Dh - 320x200 32K (1:5:5:5)
- 10Eh - 320x200 64K (5:6:5)
- 10Fh - 320x200 16.8M (8:8:8)
- 110h - 640x480 32K (1:5:5:5)
- 111h - 640x480 64K (5:6:5)
- 112h - 640x480 16.8M (8:8:8)
- 113h - 800x600 32K (1:5:5:5)
- 114h - 800x600 64K (5:6:5)
- 115h - 800x600 16.8M (8:8:8)
- 116h - 1024x768 32K (1:5:5:5)
- 117h - 1024x768 64K (5:6:5)
- 118h - 1024x768 16.8M (8:8:8)
- 119h - 1280x1024 32K (1:5:5:5)
- 11Ah - 1280x1024 64K (5:6:5)
- 11Bh - 1280x1024 16.8M (8:8:8)
-
-
-
- Function 03h - Return current Video Mode
- -----------------------------------------
-
- Input : AH = 4Fh
- AL = 03h
-
- Returns : AX = Status
- BX = Current Video mode
-
-
- Not much to say about this one I guess...
-
-
-
- Function 05h - Set Window position / Bank Switch
- -------------------------------------------------
-
- Input : AH = 4Fh
- AL = 05h
- BH = 00h
- BL = Window nr
- Window A = 0
- Window B = 1
- DX = Window position in granularity units.
- This means bank number.
-
- Returns : AX = Status
-
-
- Now, this routine sets the window position that we talked about earlier. The
- key to making a good VESA unit is to make certain that it is the correct
- bank numbers that is passed to this function. On a SVGA card with a granularity
- of 64K each bank matches one segment of memory and one potion of the screen.
- If we want to clear out Screen we usually selects bank nr 0 and then fill
- the $A000 segment with one color. Then we want to move on to the next section
- of the screen. So we increase our banknr by 1 and do the same trick. But WAIT
- A SECOND!! This will ONLY work with granunarities of 64K. 'Cause on cards with
- a granularity of fx. 4K we might have set the window to bank 0. And we might
- have filled the entire window - but by doing this we have filled SEVERAL banks!
- With a granularity of 4K we have filled 64K / 4K = 16 banks! So the next bank
- we should set should NOT be 1 but 16!
- This is where most errors I have seen in SVGA libs lies.
-
- As we all know calling BIOS is pretty SLOW! And with small granularities we
- might have to do it MANY times during a screen-update so we're pretty lucky
- that we have the brain to use the far function address we got from function
- 01h.
- When using it we don't have to set the AX register before call. Just the BX
- and DX register. Beware though : Both AX and DX is destroyed in the call so
- be sure to save the information in them if you wanna reuse them.
-
-
- Function 06h - Set/Get logical Scanlenght
- ------------------------------------------
-
- Input : AH = 4Fh
- AL = 06h
- BL = 00h {Set scanlength}
- CX = Desired width in pixels
-
- Returns : AX = Status
- BX = Bytes per Scanline
- CX = Actual pixels per Scanline
- DX = Maximum number of scanlines based on mode and memory
-
- Input : AH = 4Fh
- AL = 06h
- BL = 01h {Get scanlength}
-
- Returns : AX = Status
- BX = Bytes per Scanline
- CX = Actual pixels per Scanline
- DX = Maximum number of Scanlines.
-
-
- Now this function can be VERY useful. It allows you to set a logical width
- in video memory. It is based on this width that you calculate the offset for
- a pixel - just like in mode $13h.
- If you set this value to a power of 2 you can make sure that there will never
- be any bank-crossing along a horizontal scanline. This can speed up your code
- if you update the screen Scanline per Scanline 'cause you only have to do a
- bank check once per Scanline - and not once per pixel as you would in fx. mode
- 640 X 480!
- Also you can use function 07h to place the actual screen anywhere in this
- logical memory and this way do hardware scrolls!
- If you plan on using 640 X 480 and you know that your video card has 1MB of RAM
- installed you could set the logical scanlength to 1024 and thereby ease the
- offset calculation from :
-
- ofs := y shl 9 + y shl 7 + X
-
- to
-
- ofs := y shl 10 + X;
-
-
- It's a waste of memory, but if you are smart you store something in the memory
- outside the screen.
-
-
- Function 07h - Set / Get display start
- ----------------------------------------
-
- Input : AH = 4Fh
- AL = 07h
- BH = 00h
- BL = 00h {set display start}
- CX = Xpos
- DX = Ypos
-
- Returns : AX = Status
-
-
- Input : AH = 4Fh
- AL = 07h
- BL = 01h {get display start}
-
- Returns : AX = Status
- BH = 00h
- CX = Xpos
- DX = Ypos
-
-
- This one sets the position of the screen in video memory.
-
-
- Function 08h - Set/Get DAC pallette control
- --------------------------------------------
-
- Input : AH = 4Fh
- AL = 08h
- BL = 00h {Set DAC pallette width}
- BH = desired number of bits per primary color
-
- Returns : AX = Status
- BH = Current number of bits per primary color
-
- Input : AH = 4Fh
- AL = 08h
- BL = 01h {get DAC pallette width}
-
- Returns : AX = Status
- BH = Current number of bits per primary color
-
-
- This function sets the DAC pallette width - check if this function is
- available by checking bit 0 in the Capabilities field in VESAInfo.
-
-
- THE CODE :
- -----------
-
- First lets get the VESA information and save it in a variable called
- VESAInfo :
-
-
- FUNCTION GetVESAInfo : boolean;
- Assembler;
- asm
- mov ah,4Fh {The usual VESA sub-function number}
- mov al,00h {This is VEAS function 00h }
- lea di,VESAInfo {load the address of VESAInfo into es:di}
- int 10h {call the BIOS interrupt}
- cmp ah,0 {ah returns 0 if succes}
- jne @fail
- mov ax,1
- jmp @out
- @fail:
- mov ax,0 {the ax register will be passed to the function}
- @out:
- end;
-
-
- The same way we get the Info for the mode we wanna set :
-
-
- FUNCTION GetVESAModeInfo(mode : word) : boolean;
- Assembler;
- asm
- mov ah,4Fh
- mov al,01h {VESA function 01h}
- xor cx,cx
- mov cx,mode {load the desired mode in cx}
- lea di,VESAModeInfo {load the address to VESAModeInfo into es:di}
- int 10h {call BIOS video interrupt}
- cmp ah,0
- jne @fail
- mov ax,1
- jmp @out
- @fail:
- mov ax,0 {we put the result in ax }
- @out:
- end;
-
-
-
- OK... Now we need to be able to switch the banks :
-
-
- Procedure SetBank(nr : word);
- Assembler;
- asm
- xor bl,bl {Window A selected}
- mov dx,nr
- call [VESAModeInfo.BankSwitch] {here we call the bankSwitch procedure}
- mov dx,nr {dx is destroyed by far procedure call}
- mov cur_page,dx {update global page variable}
- end;
-
-
- Now this routine assumes that Window A is Read/Writeable. BX desides which
- window is active bl = 0 means Window A and bl = 1 means Window B.
- It is a good idea to have a global variable that keeps track of which bank is
- active at the moment so you don't change to the bank that is allready active!
-
-
- This done I think we need to set the mode up :
-
-
- FUNCTION SetVESAMode(mode : word) : boolean;
- Assembler;
- asm
- mov ax,03h
- int 10h {start from textmode}
-
- mov ah,4Fh
- mov al,02h
- mov bx,mode
- int 10h
- cmp ah,0
- jne @fail {set the VESA mode through VESA function 02h}
-
- mov ah,4Fh
- mov al,05h
- xor bx,bx
- mov dx,0
- int 10h {set bank 0 from BIOS call this time - to be safe }
- mov cur_page,0 {initialize global page variable to bank 0}
- cmp ah,0
- jne @fail
-
- mov ax,1
- jmp @out
- @fail:
- mov ax,0 {return fail or succes to function}
- @out:
- end;
-
-
- Now lets plot a pixel, shall we ??
-
-
- PROCEDURE VESAputpixel(x, y : WORD; c : BYTE);
- VAR
- bank : WORD;
- offs : longint;
- BEGIN
-
- offs := LONGINT(y) * VESAModeInfo.Xresolution + x;
- bank := offs SHR (16-BankShiftModifier);
- offs := offs - (bank SHL (16-BankShiftModifier));
-
- IF bank <> Cur_page THEN {page = global var - active page}
- BEGIN
- cur_page := bank;
- ASM
- Xor bl,bl
- mov dx,bank
- call [VESAModeInfo.BankSwitch]
- END;
- END;
-
- ASM
- MOV AX, $A000
- MOV ES, ax
- MOV DI, WORD(offs)
- MOV AL, c
- MOV ES:[DI], AL
- END;
- END;
-
-
- Now in this routine I use a variable called BankShiftModifier. This is because
- the routine assumes a granularity of 64K when using the shr 16 and shl 16
- statements. With a granularity of fx. 4K it should be shr 12 and shl 12.
- So we'll have to calculate the modifier when we recieve the information about
- the granularity from function 01h.
-
- Case VESAModeInfo.WinGranularity of
- 1 : BankShiftModifier := 6;
- 2 : BankShiftModifier := 5;
- 4 : BankShiftModifier := 4;
- 8 : BankShiftModifier := 3;
- 16 : BankShiftModifier := 2;
- 32 : BankShiftModifier := 1;
- 64 : BankShiftModifier := 0;
- end; {With granularities smaller than 64 but with page-size 64K the
- banknr for each full segment of SVGA graphic will not be 0,1,2,3
- but multiplied with BankMult ( 2^BankShiftModifier for easy bit
- shifting) }
- BankMult := 64 div VESAModeInfo.WinGranularity;
-
- Now, I know of granularities of 64K, 32K and 4K... But it can't hurt to have
- the other posibilities as well... you never know with SVGA.
- The Variable BankMult is used for our next routine - The clear routine.
- As mentioned when discussing function 05h the banks won't be 0,1,2,3,4 and so
- on when dealing with granularities smaller than 64K. Each Segment filled is
- the same as 16 banks filled with a granularity of 4K
-
- So here goes : The ClearScreen routine :
-
-
- PROCEDURE ClearScreen(color : byte);
- VAR
- Xres, Yres : longint;
- number_of_segments : longint;
- i : integer;
- BEGIN
- Xres := VESAModeInfo.Xresolution;
- Yres := VESAModeInfo.Yresolution;
- number_of_segments := Round(((Xres * Yres)/65536)+0.5)-1;
-
- for i := 0 to number_of_segments do
- BEGIN
- SetBank(i*BankMult);
- ASM
- mov cx, 32768;
- mov ax,$A000
- mov es,ax
- xor di,di
- mov al,[color]
- mov ah,al
- rep stosw
- END;
- END;
- END;
-
-
- And now the final two small routines :
-
- Procedure SetLogicalScanline(width : word);
- Assembler;
- asm
- mov ah,4Fh
- mov al,06h
- mov bl,0
- mov cx,width
- int 10h
- end;
-
-
- Procedure SetScreenPosition(x,y : word);
- Assembler;
- asm
- mov ah,4Fh
- mov al,07h
- xor bx,bx
- mov cx,[x]
- mov dx,[y]
- int 10h
- end;
-
-
-
-
- LAST REMARKS
- -------------
-
- Well, that's about all for now.
- Hope you found this doc useful - and BTW : If you DO make anything public using
- these techniques please mention me in your greets or where ever you se fit.
- I DO love to see my name in a greeting :=)
-
- Now, this done you should all be able to code some pretty stunning SVGA games/
- demos. We can no longer say anything else : SVGA is the future of all graphic
- programming.
- A few things to take note of : All the routines presented here in this text are
- very general. The ClearScreen will do any resolution - same thing with the
- putpixel routine. But I have sacrificed speed to achieve this! If you use the
- routines in games/demos where you KNOW what resolution it will run at you
- should modify the routines and optimize them to meet those specific resolutions!
- Fx. I use a normal * to calculate the offset in the putpixel. This should off
- cause be changed to shl's when dealing with a predefined gfx-mode.
-
-
- But what now ??
- If you have any good ideas for a subject you wish to see a tutorial on please
- mail me. If I like the idea (and know anything about it :) ) I'll write a
- tut on it.
- I have spoken of a tutorial on interrupts for quite a while now....
- maybe it'll come out soon - but I also plan on doing some graphical effects.
- MAIL ME!!
-
-
- Keep on coding...
-
- Telemachos - August '97.